//
//  GGCalendarTool.m
//  ggtool
//
//  Created by engfei on 2017/4/26.
//  Copyright © 2017年 GaiGai. All rights reserved.
//

#import "GGCalendarTool.h"

@interface GGCalendarDay ()

@end

@implementation GGCalendarDay


+ (GGCalendarDay *)calendarDayWithYear:(NSUInteger)year month:(NSUInteger)month day:(NSUInteger)day {
    
    GGCalendarDay *calendarDay = [[GGCalendarDay alloc] init];
    calendarDay.day = day;
    calendarDay.month = month;
    calendarDay.year = year;
    return calendarDay;
    
}

- (BOOL)isEqualTo:(GGCalendarDay *)day {
    
    BOOL isEqual = (self.year == day.year) && (self.month == day.month) && (self.day == day.day);
    
    return isEqual;
}

- (NSDate *)date {
    
    NSDateComponents *c = [[NSDateComponents alloc] init];
    c.year = self.year;
    c.month = self.month;
    c.day = self.day;
    
    return  [[NSCalendar currentCalendar] dateFromComponents:c];
  
}


@end


@interface GGCalendarTool ()<GGCalendarLogicViewDataSource, GGCalendarLogicViewDelegate>

// 日历当天
@property (nonatomic, strong) NSDate *currentDate;
// 时间模型
@property (nonatomic, strong) GGCalendarDay *currentCalendarDay;

// 用户点击选择日历上的某一天
@property (nonatomic, strong) NSDate *selectedDate;
@property (nonatomic, strong) GGCalendarDay *selectedCalendarDay;

// 当前月份展示的日历天
@property (nonatomic, strong) NSMutableArray *calendarDays;

@property (nonatomic, strong) NSMutableArray *daysInPreviousMonth;
@property (nonatomic, strong) NSMutableArray *daysInCurrentMonth;
@property (nonatomic, strong) NSMutableArray *daysInFollowingMonth;
// 选中日期的索引
@property (nonatomic, assign) NSUInteger selectedIndex;

@end


@implementation GGCalendarTool

- (void)reloadCalendarView:(GGCalendarView *)calendarView {
    [self reloadCalendarView:calendarView withDate:nil];
}
- (void)reloadCalendarView:(GGCalendarView *)calendarView withDate:(NSDate *)date {
    [self InitializeCurrentDate];
    if (date == nil) date = self.currentDate;
    // 添加日历界面
    [self reloadLogicView:calendarView.logicView withDate:date];
}

// 上个月
- (void)goToPreviousMonthInCalendarView:(GGCalendarView *)view {
    
    self.selectedDate = [self.selectedDate dayInThePreviousMonth];
    [self reloadCalendarView:view withDate:self.selectedDate];
}

// 下个月
- (void)goToNextMonthInCalendarView:(GGCalendarView *)view {
    self.selectedDate = [self.selectedDate dayInTheFollowingMonth];
    [self reloadCalendarView:view withDate:self.selectedDate];
}


// 添加日历
- (void)reloadLogicView:(GGCalendarLogicView *)logicView withDate:(NSDate *)date {
    
    [self reloadCalendarDataWithDate:date];
    
    logicView.dataSource = self;
    logicView.delegate = self;
    // 添加数据
    [logicView reloadData];
    
    //
    if ([_delegate respondsToSelector:@selector(calendarToolMonthDidChange)]) {
        [_delegate calendarToolMonthDidChange];
    }
    
}

// 初始化当前时间
- (void)InitializeCurrentDate {
    
    self.currentDate = [NSDate date];
    
    NSDateComponents *c = [self.currentDate YMDComponents];
    self.currentCalendarDay = [GGCalendarDay calendarDayWithYear:c.year month:c.month day:c.day];
    
}

- (void)reloadCalendarDataWithDate:(NSDate *)date {
    
    self.selectedDate = date;
    
    NSDateComponents *c = [date YMDComponents];
    self.selectedCalendarDay = [GGCalendarDay calendarDayWithYear:c.year month:c.month day:c.day];
    
    NSUInteger weeksCount = [date numberOfWeeksInCurrentMonth];
    // 当前月份展示的日历天数
    self.calendarDays = [NSMutableArray arrayWithCapacity:weeksCount * 7];
    
    [self calculateDaysInPreviousMonthWithDate:date];
    [self calculateDaysInCurrentMonthWithDate:date];
    [self calculateDaysInFollowingMonthWithDate:date];
    
}


- (void)calculateDaysInPreviousMonthWithDate:(NSDate *)date {
    
    // 当前是星期几
    NSUInteger weeklyOrdinarily = [[date firstDayOfCurrentMonth] weeklyOrdinality];
    NSDate *dayInThePreviousMonth = [date dayInThePreviousMonth];
    
    NSUInteger daysCount = [dayInThePreviousMonth numberOfDaysInCurrentMonth];
    NSUInteger partialDaysCount = weeklyOrdinarily - 1;
    
    NSDateComponents *components = [dayInThePreviousMonth YMDComponents];
    
    self.daysInPreviousMonth = [NSMutableArray arrayWithCapacity:partialDaysCount];
    for (NSUInteger i = daysCount - partialDaysCount + 1; i < daysCount + 1; i++) {
        GGCalendarDay *calendarDay = [GGCalendarDay calendarDayWithYear:components.year month:components.month day:i];
        [self.daysInPreviousMonth addObject:calendarDay];
        [self.calendarDays addObject:calendarDay];
    }
}

- (void)calculateDaysInCurrentMonthWithDate:(NSDate *)date {
    
    NSUInteger daysCount = [date numberOfDaysInCurrentMonth];
    NSDateComponents *components = [date YMDComponents];
    
    self.daysInCurrentMonth = [NSMutableArray arrayWithCapacity:daysCount];
    for (int i = 1; i < daysCount + 1; i++) {
        GGCalendarDay *calendarDay = [GGCalendarDay calendarDayWithYear:components.year month:components.month day:i];
        [self.daysInCurrentMonth addObject:calendarDay];
        [self.calendarDays addObject:calendarDay];
    }
}

- (void)calculateDaysInFollowingMonthWithDate:(NSDate *)date {
    
    NSUInteger weeklyOrdinaity = [[date lastDayOfCurrentMonth] weeklyOrdinality];
    if (weeklyOrdinaity == 7) return ;
    
    NSUInteger partialDaysCount = 7 - weeklyOrdinaity;
    NSDateComponents *components = [[date dayInTheFollowingMonth] YMDComponents];
    
    self.daysInFollowingMonth = [NSMutableArray arrayWithCapacity:partialDaysCount];
    for (int i = 1; i < partialDaysCount + 1; ++i) {
        GGCalendarDay *calendarDay = [GGCalendarDay calendarDayWithYear:components.year month:components.month day:i];
        [self.daysInFollowingMonth addObject:calendarDay];
        [self.calendarDays addObject:calendarDay];
    }
    
}



#pragma mark - GGCalendarLogicViewDataSource

- (NSUInteger)numberOfRowsCalendarView:(GGCalendarLogicView *)view {
    
    return [self.selectedDate numberOfWeeksInCurrentMonth];
}

- (CGFloat)heightForRowtitleView:(GGCalendarLogicView *)view {
    return kCalendarRowHeight;
}

- (GGCalendarTitleView *)titleView:(GGCalendarLogicView *)view forRow:(NSUInteger)row column:(NSUInteger)column {
    
    GGCalendarTitleView *titleView = [view dequeueReusableTitleViewAtRow:row column:column];
    
    GGCalendarDay *calendarDay = self.calendarDays[row * 7 + column];
    [self configureTitleView:titleView withCalendarDay:calendarDay];
    
    if (titleView.selected) {
        self.selectedIndex = row * 7 + column;
    }

    return titleView;
}


- (void)configureTitleView:(GGCalendarTitleView *)titleView withCalendarDay:(GGCalendarDay *)calendarDay {
    
    titleView.titleLabel.text = [NSString stringWithFormat:@"%zd", calendarDay.day];
    
    if (calendarDay.month != self.selectedCalendarDay.month) {
        titleView.titleLabel.backgroundColor = [UIColor colorWithRed:241/255.0f green:241/255.0f blue:241/255.0f alpha:0.8f];
        titleView.titleLabel.textColor = [UIColor grayColor];
    }
    
    if ([calendarDay isEqualTo:self.selectedCalendarDay]) {
        titleView.selected = YES;
    } else {
        titleView.selected = NO;
    }
    
    if ([calendarDay isEqualTo:self.currentCalendarDay]) {
        titleView.titleLabel.textColor = [UIColor colorWithRed:249.0/255 green:75.0/255 blue:0 alpha:1];
    }
    
    
}


#pragma mark - GGCalendarLogicViewDelegate

- (void)calendarView:(GGCalendarLogicView *)view didSelectedAtRow:(NSUInteger)row column:(NSUInteger)column {
    
    GGCalendarDay *calendarDay = self.calendarDays[row * 7 + column];
    
    BOOL sameMonth = calendarDay.month == self.selectedCalendarDay.month;
    
    self.selectedIndex = row * 7 + column;
    self.selectedCalendarDay = calendarDay;
    self.selectedDate = [self.selectedCalendarDay date];
    
    if (!sameMonth) {
        [self reloadLogicView:view withDate:self.selectedDate];
    }
    
    
}




- (void)toolTest {
    
    /**
     calendarIdentifier 用户日历偏好
     
     NSCalendarIdentifierGregorian                 // 阳历
     NSCalendarIdentifierBuddhist                  // 佛历
     NSCalendarIdentifierChinese                   // 中国日历
     */
    
    NSCalendar *calendar = [NSCalendar currentCalendar];
    
    NSDate *date = [NSDate date];
    
    /**
     // 返回单元的最大范围
     NSRange minRange = [calendar minimumRangeOfUnit:NSCalendarUnitMonth];
     
     NSCalendarUnitDay
     location=1, length=28
     NSCalendarUnitHour
     location=0, length=24
     NSCalendarUnitMonth
     location=1, length=12
     */
    
    /**
     // 返回单元的最小范围
     NSRange maxRange = [calendar maximumRangeOfUnit:NSCalendarUnitMonth];
     
     NSCalendarUnitDay
     location=1, length=31
     NSCalendarUnitHour
     location=0, length=24
     NSCalendarUnitMonth
     location=1, length=12
     */
    
    // 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的范围
    NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitYear forDate:date];
    
    TFLog(@"%@", NSStringFromRange(range));

    // 返回某个特定时间(date)其对应的小的时间单元(smaller)在大的时间单元(larger)中的顺序
    // 注意 larger 的unit选择
    // 如果不指定firstWeekday ,默认星期日返回一,星期一返回二,星期六返回七
    NSUInteger integer = [calendar ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitWeekOfMonth forDate:date];
    
    TFLog(@"%zd", integer);
    
    NSTimeInterval interval;
    NSDate *firstDayOfMonth;
    
    //     用于返回日期date(参数)所在的那个日历单元unit(参数)的开始时间(sDate)。其中参数unit指定了日历单元，参数sDate用于返回日历单元的第一天，参数unitSecs用于返回日历单元的长度(以秒为单位)，参数date指定了一个特定的日期
    BOOL contain = [calendar rangeOfUnit:NSCalendarUnitMonth startDate:&firstDayOfMonth interval:&interval forDate:date];
    
    if (contain) {
        TFLog(@"firstDayOfMonth = %@", firstDayOfMonth);
        TFLog(@"interval = %f", interval);
    }
    
    
    NSUInteger index = [calendar ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonth];
    TFLog(@"%zd", index);
    
    /**
     NSDateComponents
     日期元素
     日历类的辅助类,可以从创建的的日历类对象方法中中指定unit后获取components.,从而获得元素信息
     NSDateComponents *component = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
    
     创建后需要指定year,month,day等属性.
     NSDateComponents *component = [[NSDateComponents alloc] init];
     [component setDay:1];
     [component setMonth:2];
     [component setYear:3];
     
     配合 dateFromComponents: 该方法使用,可以修改当前日历显示的时间
     */
//    NSDateComponents *component = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
//    NSDate *modificationDate =  [calendar dateFromComponents:component];

    
    
    /**
     // 从comps对象转换为NSDate对象
      - (nullable NSDate *)dateFromComponents:(NSDateComponents *)comps;
     */
    
    /**
     // 从date对象获得unitFlags的时间元素,返回NSDateComponents对象
      - (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)date;
     */
    
    /**
   // date 加上设置的comps后,返回新的NSDate对象
     NSDateComponents *addComponents = [[NSDateComponents alloc] init];
     [addComponents setYear:2000];
     [addComponents setMonth:2];
     
     NSDate *addDate = [calendar dateByAddingComponents:addComponents toDate:[NSDate date] options:NSCalendarMatchStrictly];
     
     */
    
    /**
     可以获得起始/终止时间之间的间隔，用NSDateComponents来表示
     - (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSCalendarOptions)opts;
     */
    
//    NSDateComponents *addComponents = [[NSDateComponents alloc] init];
//    [addComponents setYear:2000];
//    [addComponents setMonth:2];
//    [addComponents setDay:30];
//    [addComponents setHour:12];
//    
//    NSDateComponents *addDate = [calendar components:NSCalendarUnitDay fromDate:[NSDate date] toDate:[NSDate date] options:NSCalendarMatchStrictly];
//
//    TFLog(@"%@", addDate);
//    
//
//    /**
//     // 从date对象中获组件uinit的值
//     - (NSInteger)component:(NSCalendarUnit)unit fromDate:(NSDate *)date
//     */
//    
//    NSDate *startDate = [calendar startOfDayForDate:[NSDate date]];
//    
//    TFLog(@"%@", startDate);
//    
//    BOOL isToday = [calendar isDateInToday:[NSDate date]];
//    TFLog(@"isToday = %d", isToday);
//    
// 
//    BOOL isYesterday = [calendar isDateInYesterday:[NSDate date]];
//    TFLog(@"isYesterday = %d", isYesterday);
//    
//
//    BOOL isTomorrow = [calendar isDateInTomorrow:[NSDate date]];
//    TFLog(@"isTomrrow = %d", isTomorrow);
//    
//
//    BOOL isWeekEnd = [calendar isDateInWeekend:[NSDate date]];
//    TFLog(@"isWeekEnd = %d", isWeekEnd);
//    
//    
//    /**
//     找到周末在给定日期的范围,通过两个按引用调用参数返回。
//     */
//    NSDate *outDate;
//    NSTimeInterval outTime;
//    NSDateComponents *component = [[NSDateComponents alloc] init];
//    [component setYear:2017];
//    [component setMonth:4];
//    [component setDay:30];
//    
//    NSDate *weekEndDate = [calendar dateFromComponents:component];
//    
//    BOOL weekEndStart = [calendar rangeOfWeekendStartDate:&outDate interval:&outTime containingDate:weekEndDate];
//    TFLog(@"weekEndStart = %d", weekEndStart);
//    TFLog(@"outDate = %@, outTime = %f", outDate, outTime);

    
    NSDateComponents *c = [[NSCalendar currentCalendar] components:NSCalendarUnitMonth fromDate:[NSDate date]];
    c.month = 8;
    
    NSDate *d = [[NSCalendar currentCalendar] dateByAddingComponents:c toDate:[NSDate date] options:0];
    TFLog(@"%@", d);
    

    
}

@end
